package work.parabola.keyboardswitch.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import work.parabola.keyboardswitch.common.ResponseCode;
import work.parabola.keyboardswitch.common.ServerResponse;
import work.parabola.keyboardswitch.dao.*;
import work.parabola.keyboardswitch.pojo.UserSession;
import work.parabola.keyboardswitch.pojo.query.storeswitch.InputQuery;
import work.parabola.keyboardswitch.pojo.query.storeswitch.ListQuery;
import work.parabola.keyboardswitch.pojo.query.storeswitch.NoteQuery;
import work.parabola.keyboardswitch.pojo.query.storeswitch.OutputQuery;
import work.parabola.keyboardswitch.pojo.repository.*;
import work.parabola.keyboardswitch.pojo.vo.storeswitch.StoreSwitchDetailVo;
import work.parabola.keyboardswitch.pojo.vo.storeswitch.StoreSwitchListVo;
import work.parabola.keyboardswitch.service.IStoreSwitchService;
import work.parabola.keyboardswitch.service.ISwitchTypeService;
import work.parabola.keyboardswitch.util.BigDecimalUtil;
import work.parabola.keyboardswitch.util.DateTimeUtil;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class StoreSwitchServiceImpl implements IStoreSwitchService {

    @Autowired
    private StoreSwitchDoMapper storeSwitchDoMapper;

    @Autowired
    private StoreSwitchInputDoMapper storeSwitchInputDoMapper;

    @Autowired
    private StoreSwitchOutputDoMapper storeSwitchOutputDoMapper;

    @Autowired
    private ManufacturerDoMapper manufacturerDoMapper;

    @Autowired
    private SwitchTypeDoMapper switchTypeDoMapper;

    @Autowired
    private AuthorDoMapper authorDoMapper;

    @Autowired
    private SwitchDoMapper switchDoMapper;

    @Autowired
    private ISwitchTypeService iSwitchTypeService;

    @Override
    public ServerResponse getAdminSwitchStoreList(ListQuery listQuery, UserSession userSession) {
        if (listQuery == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        ServerResponse response = listQuery.validate();
        if (!response.isSuccess()) {
            return response;
        }
        List<StoreSwitchDo> storeSwitchDoList = this.storeSwitchDoMapper.selectByParams(listQuery.getSearchWord(),
                userSession.getId(), listQuery.getAmountDescOrder(), listQuery.getPriceDescOrder());
        List<StoreSwitchListVo> storeSwitchListVoList = new ArrayList<>();

        List<Integer> switchTypeList = this.iSwitchTypeService.getSwitchTypeListByParentId(listQuery.getSwitchType());
        Set<Integer> switchTypeSet = new HashSet<>();
        switchTypeList.forEach(item -> switchTypeSet.add(item));

        for (StoreSwitchDo storeSwitchDo : storeSwitchDoList) {
            SwitchDo switchDo = this.switchDoMapper.selectByPrimaryKey(storeSwitchDo.getSwitchId());
            if (!switchTypeSet.isEmpty() && !switchTypeSet.contains(switchDo.getSwitchTypeId())) {
                continue;
            }


            StoreSwitchListVo vo = new StoreSwitchListVo();
            vo.setId(storeSwitchDo.getId());
            vo.setPos(storeSwitchDo.getPos());
            vo.setSwitchId(storeSwitchDo.getSwitchId());


            vo.setSwitchSimpleName(switchDo.getSimpleName());
            vo.setManufacturerId(switchDo.getManufacturerId());

            ManufacturerDo manufacturerDo = this.manufacturerDoMapper.selectByPrimaryKey(switchDo.getManufacturerId());
            if (manufacturerDo != null) {
                vo.setManufacturerName(manufacturerDo.getName());
            }
            vo.setAuthorId(switchDo.getAuthorId());

            AuthorDo authorDo = this.authorDoMapper.selectByPrimaryKey(switchDo.getAuthorId());
            if (authorDo != null) {
                vo.setAuthorName(authorDo.getName());
            }
            vo.setPrice(storeSwitchDo.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP).toString());
            if (storeSwitchDo.getSalePrice() == null) {
                vo.setSalePrice("0");
            } else {
                vo.setSalePrice(storeSwitchDo.getSalePrice().setScale(2, BigDecimal.ROUND_HALF_UP).toString());
            }

            if (switchDo.getSwitchTypeId() != null) {
                vo.setSwitchType(this.switchTypeDoMapper.selectByPrimaryKey(switchDo.getSwitchTypeId()).getName());
            }

            vo.setAmount(storeSwitchDo.getAmount());
            vo.setNote(storeSwitchDo.getNote());

            storeSwitchListVoList.add(vo);
        }
        return ServerResponse.createBySuccess(storeSwitchListVoList);
    }

    @Override
    public ServerResponse refreshAdminSwitchStore(UserSession userSession) {
        List<SwitchDo> switchDoList = this.switchDoMapper.selectByParam(null,
                false, false);
        List<StoreSwitchDo> storeSwitchDoList = this.storeSwitchDoMapper.selectByParams(null,
                userSession.getId(), null, null);
        int maxPos = 0;
        if (storeSwitchDoList.size() > 0) {
            maxPos = storeSwitchDoList.get(storeSwitchDoList.size() - 1).getPos() + 1;
        }
        Map<Integer, Integer> storeSwitchDoMap = new HashMap<>();
        for (StoreSwitchDo storeSwitchDo : storeSwitchDoList) {
            storeSwitchDoMap.put(storeSwitchDo.getSwitchId(), 0);
        }
        for (SwitchDo switchDo : switchDoList) {
            if (storeSwitchDoMap.containsKey(switchDo.getId())) {
                continue;
            }
            StoreSwitchDo insertRecord = new StoreSwitchDo();
            insertRecord.setPos(maxPos++);
            insertRecord.setSwitchId(switchDo.getId());
            insertRecord.setPrice(BigDecimalUtil.ZERO_SCALE_2);
            insertRecord.setAmount(0);
            insertRecord.setUserId(userSession.getId());
            this.storeSwitchDoMapper.insertSelective(insertRecord);
        }
        return ServerResponse.createBySuccessMessage("更新库存成功");
    }

    @Override
    @Transactional
    public ServerResponse upwardAdminSwitchStore(Integer id, UserSession userSession, Integer count) {
        if (id == null || count == null || count.compareTo(0) < 0) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        StoreSwitchDo storeSwitchDo = this.storeSwitchDoMapper.selectByPrimaryKeyUserId(id, userSession.getId());
        if (storeSwitchDo == null) {
            return ServerResponse.createByErrorMessage("库存不存在");
        }
        List<StoreSwitchDo> storeSwitchDoList = this.storeSwitchDoMapper.selectByParams(null, userSession.getId(),
                false, false);
        List<StoreSwitchDo> targetList = storeSwitchDoList.stream().filter(item ->
                item.getPos().compareTo(storeSwitchDo.getPos()) <= 0 &&
                        item.getPos().compareTo(storeSwitchDo.getPos() - count) >= 0)
                .collect(Collectors.toList());
        targetList.sort(Comparator.comparing(StoreSwitchDo::getPos));
        for (int i = targetList.size() - 1; i >= 0; i--) {
            StoreSwitchDo updateRecord = new StoreSwitchDo();
            StoreSwitchDo target = targetList.get(i);
            if (i == targetList.size() - 1) {
                updateRecord.setId(target.getId());
                updateRecord.setPos(targetList.get(0).getPos());
                this.storeSwitchDoMapper.updateByPrimaryKeySelective(updateRecord);
                continue;
            }
            updateRecord.setId(target.getId());
            updateRecord.setPos(target.getPos() + 1);
            this.storeSwitchDoMapper.updateByPrimaryKeySelective(updateRecord);
        }
        return ServerResponse.createBySuccessMessage("上移成功");
    }

    @Override
    @Transactional
    public ServerResponse downwardAdminSwitchStore(Integer id, UserSession userSession, Integer count) {
        if (id == null || count == null || count.compareTo(0) < 0) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        StoreSwitchDo storeSwitchDo = this.storeSwitchDoMapper.selectByPrimaryKeyUserId(id, userSession.getId());
        if (storeSwitchDo == null) {
            return ServerResponse.createByErrorMessage("库存不存在");
        }
        List<StoreSwitchDo> storeSwitchDoList = this.storeSwitchDoMapper.selectByParams(null, userSession.getId(),
                false, false);
        List<StoreSwitchDo> targetList = storeSwitchDoList.stream().filter(
                item -> item.getPos().compareTo(storeSwitchDo.getPos()) >= 0 &&
                        item.getPos().compareTo(storeSwitchDo.getPos() + count) <= 0
        )
                .collect(Collectors.toList());
        targetList.sort(Comparator.comparing(StoreSwitchDo::getPos));
        for (int i = 0; i < targetList.size(); i++) {
            StoreSwitchDo updateRecord = new StoreSwitchDo();
            StoreSwitchDo target = targetList.get(i);
            if (i == 0) {
                updateRecord.setId(target.getId());
                updateRecord.setPos(targetList.get(targetList.size() - 1).getPos());
                this.storeSwitchDoMapper.updateByPrimaryKeySelective(updateRecord);
                continue;
            }
            updateRecord.setId(target.getId());
            updateRecord.setPos(target.getPos() - 1);
            this.storeSwitchDoMapper.updateByPrimaryKeySelective(updateRecord);
        }
        return ServerResponse.createBySuccessMessage("下移成功");
    }

    @Override
    public ServerResponse updateAdminSwitchStoreNote(NoteQuery noteQuery, UserSession userSession) {
        if (noteQuery == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        ServerResponse response = noteQuery.validate();
        if (!response.isSuccess()) {
            return response;
        }

        StoreSwitchDo storeSwitchDo = this.storeSwitchDoMapper.selectByPrimaryKeyUserId(noteQuery.getId(),
                userSession.getId());
        if (storeSwitchDo == null) {
            return ServerResponse.createByErrorMessage("库存不存在");
        }
        storeSwitchDo.setNote(noteQuery.getNote());
        storeSwitchDo.setSalePrice(noteQuery.getSalePriceDecimal());
        int rowCount = this.storeSwitchDoMapper.updateByPrimaryKey(storeSwitchDo);
        if (rowCount == 0) {
            return ServerResponse.createByErrorMessage("修改备注失败");
        }
        return ServerResponse.createBySuccessMessage("修改备注成功");

    }

    @Override
    @Transactional
    public ServerResponse inputAdminSwitchStore(InputQuery inputQuery, UserSession userSession) {
        if (inputQuery == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        ServerResponse response = inputQuery.validate();
        if (!response.isSuccess()) {
            return response;
        }
        StoreSwitchDo storeSwitchDo = this.storeSwitchDoMapper.selectByPrimaryKeyUserId(inputQuery.getId(),
                userSession.getId());
        if (storeSwitchDo == null) {
            return ServerResponse.createByErrorMessage("库存不存在");
        }
        StoreSwitchInputDo storeSwitchInputDo = new StoreSwitchInputDo();
        storeSwitchInputDo.setSwitchId(storeSwitchDo.getSwitchId());
        storeSwitchInputDo.setPrice(inputQuery.getPriceDecimal());
        storeSwitchInputDo.setAmount(inputQuery.getAmountInt());
        storeSwitchInputDo.setStoreSwitchId(storeSwitchDo.getId());
        storeSwitchInputDo.setUserId(userSession.getId());

        int rowCount = this.storeSwitchInputDoMapper.insertSelective(storeSwitchInputDo);
        if (rowCount == 0) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ServerResponse.createByErrorMessage("入库失败");
        }
        Integer totalAmount = storeSwitchDo.getAmount() + inputQuery.getAmountInt();
        BigDecimal totalPrice = BigDecimalUtil.add(
                BigDecimalUtil.mulInt(storeSwitchDo.getPrice(), storeSwitchDo.getAmount(), 2),
                BigDecimalUtil.mulInt(inputQuery.getPriceDecimal(), inputQuery.getAmountInt(), 2), 2
        );
        StoreSwitchDo updateRecord = new StoreSwitchDo();
        updateRecord.setId(storeSwitchDo.getId());
        updateRecord.setPrice(totalPrice.divide(new BigDecimal(totalAmount), 2, BigDecimal.ROUND_HALF_UP));
        updateRecord.setAmount(totalAmount);
        rowCount = this.storeSwitchDoMapper.updateByPrimaryKeySelective(updateRecord);
        if (rowCount == 0) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ServerResponse.createByErrorMessage("入库失败");
        }
        return ServerResponse.createBySuccessMessage("入库成功");
    }

    @Override
    @Transactional
    public ServerResponse outputAdminSwitchStore(OutputQuery outputQuery, UserSession userSession) {
        if (outputQuery == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        ServerResponse response = outputQuery.validate();
        if (!response.isSuccess()) {
            return response;
        }
        StoreSwitchDo storeSwitchDo = this.storeSwitchDoMapper.selectByPrimaryKeyUserId(outputQuery.getId(),
                userSession.getId());
        if (storeSwitchDo == null) {
            return ServerResponse.createByErrorMessage("库存不存在，无法出库");
        }
        if (storeSwitchDo.getAmount().compareTo(outputQuery.getAmountInt()) < 0) {
            return ServerResponse.createByErrorMessage("库存不足，无法出库");
        }
        StoreSwitchOutputDo storeSwitchOutputDo = new StoreSwitchOutputDo();
        storeSwitchOutputDo.setSwitchId(storeSwitchDo.getSwitchId());
        storeSwitchOutputDo.setAmount(outputQuery.getAmountInt());
        storeSwitchOutputDo.setStoreSwitchId(storeSwitchDo.getId());
        storeSwitchOutputDo.setUserId(userSession.getId());
        int rowCount = this.storeSwitchOutputDoMapper.insertSelective(storeSwitchOutputDo);
        if (rowCount == 0) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ServerResponse.createByErrorMessage("出库失败");
        }
        StoreSwitchDo updateRecord = new StoreSwitchDo();
        updateRecord.setId(storeSwitchDo.getId());
        updateRecord.setAmount(storeSwitchDo.getAmount() - outputQuery.getAmountInt());
        rowCount = this.storeSwitchDoMapper.updateByPrimaryKeySelective(updateRecord);
        if (rowCount == 0) {
            return ServerResponse.createByErrorMessage("出库失败");
        }
        return ServerResponse.createBySuccessMessage("出库成功");
    }

    @Override
    public ServerResponse getAdminSwitchStoreDetail(Integer id, UserSession userSession) {
        if (id == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        StoreSwitchDo storeSwitchDo = this.storeSwitchDoMapper.selectByPrimaryKeyUserId(id,
                userSession.getId());
        if (storeSwitchDo == null) {
            return ServerResponse.createByErrorMessage("库存信息在存在");
        }
        List<StoreSwitchInputDo> storeSwitchInputDoList = this.storeSwitchInputDoMapper.selectByStoreSwitchId(id);
        List<StoreSwitchOutputDo> storeSwitchOutputDoList = this.storeSwitchOutputDoMapper.selectByStoreSwitchId(id);
        List<StoreSwitchDetailVo> storeSwitchDetailVoList = new ArrayList<>();
        final String inputDesc = "入库";
        final String outputDesc = "出库";
        for (StoreSwitchInputDo storeSwitchInputDo : storeSwitchInputDoList) {
            StoreSwitchDetailVo vo = new StoreSwitchDetailVo();
            vo.setDesc(inputDesc);
            vo.setAmount(storeSwitchInputDo.getAmount());
            vo.setCreateTime(storeSwitchInputDo.getCreateTime());
            vo.setCreateTimeDesc(DateTimeUtil.dateToStr(storeSwitchInputDo.getCreateTime(),
                    DateTimeUtil.FULL_FORMAT));
            storeSwitchDetailVoList.add(vo);
        }
        for (StoreSwitchOutputDo storeSwitchOutputDo : storeSwitchOutputDoList) {
            StoreSwitchDetailVo vo = new StoreSwitchDetailVo();
            vo.setDesc(outputDesc);
            vo.setAmount(storeSwitchOutputDo.getAmount());
            vo.setCreateTime(storeSwitchOutputDo.getCreateTime());
            vo.setCreateTimeDesc(DateTimeUtil.dateToStr(storeSwitchOutputDo.getCreateTime(),
                    DateTimeUtil.FULL_FORMAT));
            storeSwitchDetailVoList.add(vo);
        }
        storeSwitchDetailVoList.sort(Comparator.comparing(StoreSwitchDetailVo::getCreateTime));
        for (int i = 0; i < storeSwitchDetailVoList.size(); i++) {
            StoreSwitchDetailVo vo = storeSwitchDetailVoList.get(i);
            if (i == 0) {
                vo.setBalance(vo.getAmount());
                continue;
            }
            StoreSwitchDetailVo preVo = storeSwitchDetailVoList.get(i - 1);
            if (vo.getDesc().equals(inputDesc)) {
                vo.setBalance(vo.getAmount() + preVo.getBalance());
            } else {
                vo.setBalance(preVo.getBalance() - vo.getAmount());
            }
        }
        return ServerResponse.createBySuccess(storeSwitchDetailVoList);
    }

    @Override
    @Transactional
    public ServerResponse deleteAdminSwitchStoreItem(Integer id, UserSession userSession) {
        if (id == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        StoreSwitchDo storeSwitchDo = this.storeSwitchDoMapper.selectByPrimaryKeyUserId(id, userSession.getId());
        if (storeSwitchDo == null) {
            return ServerResponse.createByErrorMessage("库存信息不存在");
        }
        StoreSwitchInputDo storeSwitchInputDo = this.storeSwitchInputDoMapper.selectOneByStoreSwitchId(storeSwitchDo.getId());
        StoreSwitchOutputDo storeSwitchOutputDo = this.storeSwitchOutputDoMapper.
                selectOneByStoreSwitchId(storeSwitchDo.getId());
        if (storeSwitchInputDo == null) {
            return ServerResponse.createBySuccessMessage("删除成功");
        }
        if (storeSwitchOutputDo == null) {
            int rowCount = this.storeSwitchInputDoMapper.deleteByPrimaryKey(storeSwitchInputDo.getId());
            if (rowCount == 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ServerResponse.createByErrorMessage("删除失败");
            }
            StoreSwitchDo updateRecord = new StoreSwitchDo();
            updateRecord.setId(storeSwitchDo.getId());
            updateRecord.setAmount(storeSwitchDo.getAmount() - storeSwitchInputDo.getAmount());
            rowCount = this.storeSwitchDoMapper.updateByPrimaryKeySelective(updateRecord);
            if (rowCount == 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ServerResponse.createByErrorMessage("删除失败");
            }
            return ServerResponse.createBySuccessMessage("删除成功");
        }
        if (storeSwitchInputDo.getCreateTime().compareTo(storeSwitchOutputDo.getCreateTime()) == 0) {
            return ServerResponse.createByErrorMessage("数据错误，出入库时间相同");
        }
        if (storeSwitchInputDo.getCreateTime().compareTo(storeSwitchOutputDo.getCreateTime()) > 0) {
            //最后操作是入库
            int rowCount = this.storeSwitchInputDoMapper.deleteByPrimaryKey(storeSwitchInputDo.getId());
            if (rowCount == 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ServerResponse.createByErrorMessage("删除失败");
            }
            StoreSwitchDo updateRecord = new StoreSwitchDo();
            updateRecord.setId(storeSwitchDo.getId());
            updateRecord.setAmount(storeSwitchDo.getAmount() - storeSwitchInputDo.getAmount());
            rowCount = this.storeSwitchDoMapper.updateByPrimaryKeySelective(updateRecord);
            if (rowCount == 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ServerResponse.createByErrorMessage("删除失败");
            }
        } else {
            //最后操作是出库
            int rowCount = this.storeSwitchOutputDoMapper.deleteByPrimaryKey(storeSwitchOutputDo.getId());
            if (rowCount == 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ServerResponse.createByErrorMessage("删除失败");
            }
            StoreSwitchDo updateRecord = new StoreSwitchDo();
            updateRecord.setId(storeSwitchDo.getId());
            updateRecord.setAmount(storeSwitchDo.getAmount() + storeSwitchOutputDo.getAmount());
            rowCount = this.storeSwitchDoMapper.updateByPrimaryKeySelective(updateRecord);
            if (rowCount == 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ServerResponse.createByErrorMessage("删除失败");
            }
        }
        return ServerResponse.createBySuccessMessage("删除成功");
    }
}
